/*******************************************************************************
 * Copyright 2009 Dop Sun
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
/**
 * Place holder for copyright, needs to be replaced before release.
 */
package com.softao.ming.gde.internal.core.export;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipFile;

import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.pde.core.plugin.IPluginModelBase;
import org.eclipse.pde.core.plugin.PluginRegistry;
import org.eclipse.pde.internal.build.ant.AntScript;
import org.eclipse.pde.internal.build.ant.FileSet;

import com.softao.ming.gde.internal.core.ant.GwtCompileTask;
import com.softao.ming.gde.internal.core.bootstrap.BootstrapGeneratorArgs;
import com.softao.ming.gde.internal.core.launcher.LaunchUtil;
import com.softao.ming.gde.internal.core.natures.GdePluginFile;

/**
 * Generates the ant file for {@link GdeApplicationExportOperation}.
 */
@SuppressWarnings("restriction")
public class AntFileGenerator {
	/**
	 * @param exportInfo 
	 * @param args
	 * @param monitor
	 * @return generates the target.
	 */
	public IPath generate(GdeApplicationExportInfo exportInfo, BootstrapGeneratorArgs args, IProgressMonitor monitor) {
		File antFile = new File(args.getLocation(), "build.xml");
		IPath result = new Path(antFile.toString());
		
		try {
			FileOutputStream antFileOutputStream = new FileOutputStream(antFile);
			printAntFile(antFileOutputStream, exportInfo, args);
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
		return result;
	}
	
	@SuppressWarnings("unchecked")
	private List getClassPath(GdeApplicationExportInfo exportInfo, BootstrapGeneratorArgs args) {
		List<String> result = new ArrayList<String>();
		for (IPluginModelBase plugin : PluginRegistry.getActiveModels()) {
			String installLocation = plugin.getInstallLocation();
			File file = new File(installLocation);
			
			if (file.isFile()) {
				try {
					ZipFile zipFile = new ZipFile(file, ZipFile.OPEN_READ);
					if (zipFile.getEntry(GdePluginFile.FILE_NAME) != null) {
						result.add(file.getPath());
					}
					zipFile.close();
				} catch (IOException e) {
					e.printStackTrace();
					continue;
				}
				
			} else {
				File gwtPluginFile = new File(file, GdePluginFile.FILE_NAME);
				if (!gwtPluginFile.exists()) {
					continue;
				}
				result.add(file.getPath());
				
				File buildFile = new File(file, "build.properties");
				if (!buildFile.exists()) {
					continue;
				}
				
				String[] sourceFolders;
				try {
					InputStream buildEntryStream = new FileInputStream(buildFile);
					sourceFolders = LaunchUtil.getSourceFolders(buildEntryStream);
					buildEntryStream.close();
					
					if (sourceFolders.length == 0) {
						continue;
					}
				} catch (IOException e) {
					e.printStackTrace();
					continue;
				}

				for (String sourceFolder : sourceFolders) {
					File sourceFile = new File(file, sourceFolder);
					result.add(sourceFile.getPath());
				}
			}
		}
		
		String gwtLocation = exportInfo.getGwtLocation();
		File gwtFile = new File(gwtLocation);
		result.add((new File(gwtFile, "gwt-dev-windows.jar")).getPath());
		result.add((new File(gwtFile, "gwt-servlet.jar")).getPath());
		result.add((new File(gwtFile, "gwt-user.jar")).getPath());
		
		result.add(args.getLocation());
		return result;
	}
		
	@SuppressWarnings({"unchecked" })
	private void printAntFile(FileOutputStream antFileOutputStream, GdeApplicationExportInfo exportInfo, BootstrapGeneratorArgs args) throws IOException {
		final String gwtEntryModule = "com.softao.ming.gwt.bootstrap.MingBootstrap";
		
		List classPath = getClassPath(exportInfo, args);
		AntScript antScript = new AntScript(antFileOutputStream);
		antScript.printProjectDeclaration("test", "build", args.getLocation());
		antScript.printPathStructure("path", "build.classpath", classPath);
		
		antScript.printTargetDeclaration("compile", null, null, null, null);
		GwtCompileTask gwtCompileTask = new GwtCompileTask();
		gwtCompileTask.setClasspathId("build.classpath");
		gwtCompileTask.setEntryPointClass(gwtEntryModule);
		gwtCompileTask.setOutputLocation(args.getLocation() + "/out");
		antScript.print(gwtCompileTask);
		antScript.printEndTag("target");
		
		antScript.printTargetDeclaration("copy-jars", null, null, null, null);
		for (String jarFilePath : getReferencedJars(exportInfo, args)) {
			File jarFile = new File(jarFilePath);
			String name = jarFile.getName();
			antScript.printCopyFileTask(jarFilePath, args.getLocation() + "/out/com.softao.ming.gwt.bootstrap.MingBootstrap/WEB-INF/lib/" + name, true);
		}
		antScript.printEndTag("target");

		antScript.printTargetDeclaration("copy-config", null, null, null, null);
		String configPath = exportInfo.getConfigurationLocation();
		if (configPath != null && configPath.trim().length() > 0) {
			antScript.printCopyTask(null, 
					args.getLocation() + "/out/com.softao.ming.gwt.bootstrap.MingBootstrap/WEB-INF/classes/", 
					new FileSet[] {new FileSet(configPath, null, "*.*", null, null, null, null)}, true, true);
		}
		antScript.printEndTag("target");

		antScript.printTargetDeclaration("build", "compile, copy-jars, copy-config", null, null, null);
		antScript.printEndTag("target");
		
		antScript.printEndTag("project");
		antScript.close();
	}
	
	private List<String> getReferencedJars(GdeApplicationExportInfo exportInfo, BootstrapGeneratorArgs args) {
		List<String> result = new ArrayList<String>();
		for (IPluginModelBase plugin : PluginRegistry.getActiveModels()) {
			String installLocation = plugin.getInstallLocation();
			File file = new File(installLocation);
			
			if (file.isFile()) {
				try {
					ZipFile zipFile = new ZipFile(file, ZipFile.OPEN_READ);
					if (zipFile.getEntry(GdePluginFile.FILE_NAME) != null) {
						result.add(file.getPath());
					}
					zipFile.close();
				} catch (IOException e) {
					e.printStackTrace();
					continue;
				}
			}
		}
		
		String gwtLocation = exportInfo.getGwtLocation();
		File gwtFile = new File(gwtLocation);
		result.add((new File(gwtFile, "gwt-servlet.jar")).getPath());
		result.add((new File(gwtFile, "gwt-user.jar")).getPath());
		
		File compiledJarsDir = new File(args.getLocation() + "/temp/plugins");
		for (File file : compiledJarsDir.listFiles()) {
			if (file.isFile()) {
				result.add(file.getPath());
			}
		}
		return result;
	}

}
